/*
Automatic clinic tests using a robot arm.
Copyright (C) 2010  CIC-CPC, CHU Gabriel Montpied
All other trademarks, logos and copyrights are the property
of their respective owners.

This file is part of cpc-painbot.

cpc-painbot is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

cpc-painbot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with cpc-painbot.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef CPC_PAINBOT_INDICATEURPROCESS_H
#define CPC_PAINBOT_INDICATEURPROCESS_H
#include "pilotableserie.h"

#include <QBasicTimer>
#include <QList>

namespace commande {
namespace indproc {
class Ascii;
}
}

class Capteur;

/*! Indicateur de process.
    Un indicateur de process sert d'intermédiaire entre un capteur
    analogique et une interface numérique.
    Par exemple, les capteurs laser de distance qui équipent le robot
    sont reliés à des indicateurs de process.
    Les valeurs sont transférées via un lien RS232.
*/
class IndicateurProcess : public PilotableSerie
{
Q_OBJECT
//! Minimum relevé.
Q_PROPERTY(qreal min READ min RESET resetMin NOTIFY minChange)
//! Maximum relevé.
Q_PROPERTY(qreal max READ max RESET resetMax NOTIFY maxChange)
//! Tare de l'indicateur.
Q_PROPERTY(qreal tare READ tare WRITE setTare RESET resetTare NOTIFY tareChangee)
//! Intervalle de mesure (en ms).
Q_PROPERTY(int intervalle READ intervalle WRITE setIntervalle)
//! Capteur lié.
Q_PROPERTY(Capteur* capteur READ capteur WRITE setCapteur)
//! Adresse de l'indicateur.
Q_PROPERTY(int adresse READ adresse WRITE setAdresse NOTIFY adresseChangee)
//! Etat courant.
Q_PROPERTY(Etat etat READ etat)
//! Liste des Etats.
Q_ENUMS(Etat)
public:
    /*! Etats de l'indicateur. */
    enum Etat {
        EtatAttente,      //!< Attente de commande.
        EtatLectureMin,   //!< Lecture de la valeur minimale.
        EtatResetMin,     //!< Remise à zéro de la valeur minimale.
        EtatLectureMax,   //!< Lecture de la valeur maximale.
        EtatResetMax,     //!< Remise à zéro de la valeur maximale.
        EtatLectureTare,  //!< Lecture de la tare.
        EtatResetTare,    //!< Remise à zéro de la tare.
        EtatEcritureTare, //!< Définition de la tare.
        EtatLireMesure    //!< Lecture de la mesure courante.
    };

    //! Constructeur.
    IndicateurProcess(QObject *parent = 0);

    //! Destructeur.
    ~IndicateurProcess();

    //! Valeur minimale.
    qreal min(void) const { return min_; }

    //! Valeur maximale.
    qreal max(void) const { return max_; }

    //! Valeur de la tare.
    qreal tare(void) const { return tare_; }

    //! Intervalle des mesures.
    int intervalle(void) const { return intervalle_; }

    //! Capteur lié à cet indicateur.
    Capteur * capteur(void) const { return capteur_; }

    //! Adresse de l'indicateur.
    int adresse(void) const { return adresse_; }

    //! Etat de l'indicateur.
    Etat etat(void) const { return etat_; }

public slots:
    //! Mise à jour de la valeur minimale.
    void majMin(void);

    //! Effacement de la valeur minimale.
    void resetMin(void);

    //! Mise à jour de la valeur maximale.
    void majMax(void);

    //! Effacement de la valeur maximale.
    void resetMax(void);

    //! Mise à jour de la tare.
    void majTare(void);

    //! Effacement de la tare.
    void resetTare(void);

    /*! Définit la tare.
        Utilisé pour la compatibilité avec les QProperties.
        \param[in] tare La tare à définir.
    */
    void setTare(qreal tare = 0);

    /*! Définit l'intervalle.
        \param[in] intervalle_ms Nouvel intervalle de mesure (en ms)

        \attention L'intervalle doit être d'au moins 100 ms (limitations techniques).
        Si l'intervalle fourni est inférieur, la valeur 100 sera utilisée à la place.
    */
    void setIntervalle(int intervalle_ms) { intervalle_ = qMax(100, intervalle_ms); }

    /*! Prise de la mesure.
        La mesure correspond à la valeur mesurée (celle du capteur
        analogique) + la tare.
    */
    void mesure(void);

    /*! Change le capteur lié.
        \param capteur Le nouveau capteur lié à cet indicateur.
    */
    void setCapteur(Capteur *capteur);

    /*! Change l'adresse du capteur.
        \param[in] adresse La nouvelle adresse.
    */
    void setAdresse(int adresse);

    /*! Lance des mesures répétées.
        Les mesures se feront toutes les 100 ms.
    */
    void demarrer() { timer_.start(intervalle(), this); }

    /*! Arrête la capture des mesures. */
    void arreter() { timer_.stop(); }

signals:
    //! Le minimum a changé.
    void minimumChange(qreal min);

    //! Le maximum a changé.
    void maximumChange(qreal max);

    //! La tare a changé.
    void tareChangee(qreal tare);

    //! L'adresse a changé.
    void adresseChangee(int adresse);

protected:
    /*! Capture à intervalle.
        Permet la capture à intervalle régulier.
    */
    void timerEvent(QTimerEvent *event);

    //! \see PilotableSerie::configurerLiaison()
    virtual void configurerLiaison();

    //! Indique la présence d'une commande dans le buffer.
    virtual bool hasCommande() const;

    //! \see PilotableSerie::parserCommande()
    virtual void parserCommande();

    qreal       min_;       //!< Dernier minimum relevé.
    qreal       max_;       //!< Dernier maximum relevé.
    qreal       tare_;      //!< Dernière tare relevée.
    int         intervalle_;//!< Intervalle de mesure, en ms.
    Capteur     *capteur_;  //!< Capteur lié.
    int         adresse_;   //!< Adresse de l'indicateur.
    Etat        etat_;      //!< Etat courant de l'indicateur.
    QBasicTimer timer_;     //!< Gestion du timer.
    QList<commande::indproc::Ascii*> commandes_; //!< Commandes connues de l'indicateur.
};

#endif // CPC_PAINBOT_INDICATEURPROCESS_H
